﻿using System;
using System.Collections.Generic;
using Microsoft.ApplicationServer.Caching;
using RockBus.CacheManager.Interfaces;

namespace RockBus.CacheManager.AppFabric
{
    public class CacheManager : ICacheManager
    {
        private ICacheManagerConfiguration Configuration { get; set; }

        private DataCache Cache { get; set; }

        public CacheManager(ICacheManagerConfiguration configuration)
        {
            this.Configuration = configuration;
            this.PrepareCacheClient();
        }

        public void Add(string key, object value)
        {
            this.Cache.Put(key, value);
        }

        public void Add(string key, object value, int timeToLiveSecs)
        {
            this.Cache.Put(key, value, TimeSpan.FromSeconds(timeToLiveSecs));
        }

        public void Add<T>(string key, T value) where T : class
        {
            this.Cache.Put(key, value);
        }

        public void Add<T>(string key, T value, int timeToLiveSecs) where T : class
        {
            this.Cache.Put(key, value, TimeSpan.FromSeconds(timeToLiveSecs));
        }

        public object Get(string key)
        {
            return this.Cache.Get(key);
        }

        public T Get<T>(string key) where T : class
        {
            object obj = this.Cache.Get(key);
            if (null == obj)
            {
                return null;
            }

            T item = obj as T;
            if (null == item)
            {
                throw new InvalidCastException(
                    string.Format("Unable to cast object with key {0} to type {1}",
                    key,
                    typeof(T).Name));
            }

            return item;
        }

        public object Remove(string key)
        {
            object item = this.Get(key);
            this.Cache.Remove(key);
            return item;
        }

        public T Remove<T>(string key) where T : class
        {
            T item = this.Get<T>(key);
            this.Cache.Remove(key);
            return item;
        }

        private void PrepareCacheClient()
        {
            List<DataCacheServerEndpoint> servers = new List<DataCacheServerEndpoint>(1);
            servers.Add(new DataCacheServerEndpoint(this.Configuration.DataCacheServerHostName, this.Configuration.DataCacheServerPort));
            //servers.Add(new DataCacheServerEndpoint("localhost", 22233));

            DataCacheFactoryConfiguration configuration = new DataCacheFactoryConfiguration();
            configuration.Servers = servers;
            configuration.LocalCacheProperties = new DataCacheLocalCacheProperties();

            DataCacheClientLogManager.ChangeLogLevel(System.Diagnostics.TraceLevel.Off);
            DataCacheFactory factory = new DataCacheFactory(configuration);

            this.Cache = factory.GetCache(this.Configuration.CacheName);
        }
    }
}
